using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.ComponentModel;

namespace Rapier.Kodachi.Shared
{
    [Serializable]
    public class Item : ILookupItem
    {
        #region Events
        public event UpdatePropertiesEventHandler UpdateProperties;
        public event UpdateDrilledItemsEventHandler UpdateDrilledItems;
        #endregion

        #region Properties
        public string Key
        {
            get { return _Name + Plugin.Guid.ToString(); }
        }

        private Plugin _Plugin;
        public Plugin Plugin
        {
            get { return _Plugin; }
            set { _Plugin = value; }
        }

        private string _Name;
        public string Name
        {
            get { return _Name; }
            set { _Name = value; }
        }

        private string _Description;
        public string Description
        {
            get { return _Description; }
            set { _Description = value; }
        }

        private string _ItemType;
        public string ItemType
        {
            get { return _ItemType; }
            set { _ItemType = value; }
        }

        public Bitmap Image
        {
            get 
            {
                if (_GetImage != null)
                    return _GetImage();
                else
                    return null;
            }
        }
        
        private GetImageDelegate _GetImage = null;
        public GetImageDelegate GetImage
        {
            get { return _GetImage; }
            set { _GetImage = value; }
        }

        private Dictionary<string, object> _Properties = new Dictionary<string, object>();
        public Dictionary<string, object> Properties
        {
            get { return _Properties; }
        }

        private string _DefaultAction = "Launch";
        public string DefaultAction
        {
            get { return _DefaultAction; }
            set { _DefaultAction = value; }
        }

        public bool IsDrillable
        {
            get { return UpdateDrilledItems != null; }
        }

        public int MatchCount
        {
            get { return _QueryMatchCount[String.Empty]; }
            set { _QueryMatchCount[String.Empty] = value; }
        }

        private Dictionary<string, int> _QueryMatchCount = new Dictionary<string, int>();
        public Dictionary<string, int> QueryMatchCount
        {
            get { return _QueryMatchCount; }
            set { _QueryMatchCount = value; }
        }

        private bool _IndirectOnly = false;
        public bool IndirectOnly
        {
           get
           {
              return _IndirectOnly;
           }
           set
           {
              _IndirectOnly = value;
           }
        }
        #endregion

        #region Constructors
        public Item(Plugin plugin) 
        {
            _QueryMatchCount.Add(String.Empty, 0);
            _Plugin = plugin;
            _GetImage = delegate() { return Resource.DefaultItem; };
        }

        public Item(Plugin plugin, string itemType)
            : this(plugin)
        {
            _ItemType = itemType;
        }

        public Item(Plugin plugin, string itemType, string name)
            : this(plugin, itemType)
        {
            _Name = name;
        }

        public Item(Plugin plugin, string itemType, string name, string description)
            : this(plugin, itemType, name)
        {
            _Description = description;
        }
        #endregion

        #region Overrides
        public override string ToString()
        {
            return _Name;
        }

        public override bool Equals(object obj)
        {
            if(!(obj is Item))
                throw new ArgumentException("obj must be of type Item");

            return (_Name == (obj as Item)._Name && Plugin.Guid == (obj as Item).Plugin.Guid );
        }

        public override int GetHashCode()
        {
            return Key.GetHashCode();
        }
        #endregion

        #region Methods
        public virtual void OnUpdateProperties()
        {
            if(UpdateProperties != null)
                UpdateProperties(this);
        }

        public virtual void OnUpdateDrilledItems(List<ILookupItem> drilledItems)
        {
            if (UpdateDrilledItems != null)
                UpdateDrilledItems.Invoke(this, drilledItems); // Synchronous so as to prevent drilling down from corrupting item list
        }
        #endregion
    }

    public delegate void UpdatePropertiesEventHandler(Item item);
    public delegate void UpdateDrilledItemsEventHandler(Item item, List<ILookupItem> drilledItems);

    public enum ItemPosition
    {
        Direct,
        Indirect
    }
}